package com.mayisoftware.mayioa.business.pool.impl.task;

import com.mayisoftware.mayioa.business.plan.api.domain.PlanConfig;
import com.mayisoftware.mayioa.business.plan.api.domain.PlanDetailConfig;
import com.mayisoftware.mayioa.business.plan.api.service.IPlanConfigDetailService;
import com.mayisoftware.mayioa.business.plan.api.service.IPlanConfigService;
import com.mayisoftware.mayioa.business.pool.api.domain.PoolMgrInfo;
import com.mayisoftware.mayioa.business.pool.api.service.IPoolManualService;
import com.mayisoftware.mayioa.business.score.api.domain.ScoreInfo;
import com.mayisoftware.mayioa.business.score.api.service.IScoreInfoService;
import com.mayisoftware.mayioa.platform.api.service.ISysConfigService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;

/**
 * 骨干计算任务调度
 */
@Component("poolCaclTask")
public class PoolCaclTask {

    /**
     * 计划配置详情服务
     */
    @Autowired
    private IPlanConfigDetailService planConfigDetailService;

    /**
     * 计划配置服务
     */
    @Autowired
    private  IPlanConfigService planConfigService;

    /**
     * 打分统计服务
     */
    @Autowired
    private IScoreInfoService scoreInfoService;

    /**
     * 骨干池管理服务
     */
    @Autowired
    private IPoolManualService poolManualService;

    /**
     * 系统参数服务
     */
    @Autowired
    ISysConfigService sysConfigService;

    /**
     * 计划倒数N名
     */
    private final String sys_plan_lastn = "sys.plan.lastn";
    private String getSys_plan_lastn(){
        return sysConfigService.selectConfigByKey(sys_plan_lastn);
    }

    /**
     * 日志对象
     */
    private static final Logger log = LoggerFactory.getLogger(PoolCaclTask.class);

    /**
     * 一个计划内排名，分数相等排名相等
     * @param tmpInfos
     */
    public void setPlanRankByPlan(List<PoolMgrInfo> tmpInfos){
        if(tmpInfos == null || tmpInfos.isEmpty()){
            log.error("计划为空");
        }
        //倒序
        tmpInfos.sort((o1,o2)->-(o1.getPoolTotalScore().compareTo(o2.getPoolTotalScore())));
        //设置第一名，倒序第一个是最大分
        PoolMgrInfo info = tmpInfos.get(0);
        int rank=1;
        BigDecimal maxScore=info.getPoolTotalScore();
        info.setPoolPlanRankInfo(rank, tmpInfos.size(), getSys_plan_lastn());
        poolManualService.modifyPoolInfo(info);
        //设置第二名及以后
        for(int i=1;i<tmpInfos.size();i++){
            info = tmpInfos.get(i);
            //分数小于才更新，等于说明排名相等，排序后不存在大于情况
            if(info.getPoolTotalScore().compareTo(maxScore)<0){
                maxScore=info.getPoolTotalScore();
                rank++;
            }
            info.setPoolPlanRankInfo(rank, tmpInfos.size(), getSys_plan_lastn());
            poolManualService.modifyPoolInfo(info);
        }
    }

    /**
     * 所有计划排名
     * @param poolMgrInfos
     */
    public void updatePlanRank(List<PoolMgrInfo> poolMgrInfos){
        Map<Integer, List<PoolMgrInfo>> planInfos = new HashMap<Integer, List<PoolMgrInfo>>();
        for(PoolMgrInfo info : poolMgrInfos){
            if(!planInfos.containsKey(info.getPoolPlanId())){
                planInfos.put(info.getPoolPlanId(), new ArrayList<PoolMgrInfo>());
            }
            planInfos.get(info.getPoolPlanId()).add(info);
        }
        for(Map.Entry<Integer, List<PoolMgrInfo>> entry : planInfos.entrySet()){
            List<PoolMgrInfo> tmpInfos = entry.getValue();
            setPlanRankByPlan(tmpInfos);
        }
    }

    /**
     * 计算骨干信息
     */
    public void calcTask(){
//        log.info("开始统计骨干信息");

        try {
           List<PoolMgrInfo> poolMgrInfos = poolManualService.queryPoolListByStatus();

           if (CollectionUtils.isEmpty(poolMgrInfos)){
//               log.warn("没有需要重新计算的骨干信息");
               return;
           }

           //过期的用户和计划的打分信息需要重新计算
            Map<Integer,Integer> outDateUserPlanInfo = new LinkedHashMap<>();
           List<PoolMgrInfo> modifiedInfos = new ArrayList<PoolMgrInfo>();
           for (PoolMgrInfo poolMgrInfo:poolMgrInfos){
               if (poolMgrInfo.getPoolPlanId() == null){
                   continue;
               }

               Integer planId = poolMgrInfo.getPoolPlanId();
               Integer userId = poolMgrInfo.getPoolUserId();

//               log.info("开始计算计划：{} 用户{}",planId,userId);
               //查询分数信息
               ScoreInfo scoreInfo = new ScoreInfo();
               scoreInfo.setScoreUserId(userId);
               scoreInfo.setScorePlanId(planId);
               List<ScoreInfo> scoreInfos = scoreInfoService.selectScoreInfoList(scoreInfo);
               //查询计划信息
               PlanConfig planConfig = planConfigService.selectPlanConfigById(planId.longValue());
               List<PlanDetailConfig> planDetailConfigs = planConfigDetailService.selectPlanItemByPlanId(planId.longValue());

//               if (scoreInfos == null || planConfig == null || planDetailConfigs ==null){
//                   // 删除已经没有计划或者没有打分信息得记录
//                   Integer[] ids = new Integer[1];
//                   ids[0] = poolMgrInfo.getPoolRecordId();
//                   poolManualService.rmvPoolByIds(ids);
//                   log.error("删除已经没有计划或者没有打分信息得记录{}",ids[0]);
//                   continue;
//               }
               //手动入骨干池，没有计划
               if(planConfig == null){
                   continue;
               }
               //还没有打分，没有分数信息
               if(scoreInfos == null || scoreInfos.isEmpty()){
                   continue;
               }

               //转换打分为Map形式
               Map<Integer, BigDecimal> itemScoreInfo = new HashMap<>();
               for (ScoreInfo tmpInfo :scoreInfos){
                   if (tmpInfo.getScorePlanItemId() != null && tmpInfo.getScoreInfo() != null){
                       itemScoreInfo.put(tmpInfo.getScorePlanItemId(),tmpInfo.getScoreInfo());
                   }
               }

               BigDecimal totalScore = BigDecimal.valueOf(0);
               for (PlanDetailConfig planDetailConfig:planDetailConfigs){
                   if (planDetailConfig.getPlanCfgItemWeight() == null){
                       continue;
                   }
                   BigDecimal itemScore = itemScoreInfo.get(planDetailConfig.getPlanCfgItemRecordid());

                   if (itemScore == null){
                       continue;
                   }

                   totalScore=totalScore.add( itemScore.multiply(planDetailConfig.getPlanCfgItemWeight()));
               }

               PoolMgrInfo tmpMgrInfo = new PoolMgrInfo();
               tmpMgrInfo.setPoolRecordId(poolMgrInfo.getPoolRecordId());
               tmpMgrInfo.setPoolPlanId(poolMgrInfo.getPoolPlanId());
               int isPass = totalScore.compareTo(planConfig.getPlanCfgPassScore());
               if (isPass >= 0){
                   tmpMgrInfo.setPoolCreateType(0);
                   tmpMgrInfo.setPoolIsBackbone(1);
                   tmpMgrInfo.setPoolTotalScore(totalScore);
                   tmpMgrInfo.setPoolUpdateTime(new Date());
                   if (poolMgrInfo.getPoolIsBackbone() == null || poolMgrInfo.getPoolIsBackbone() ==0 || poolMgrInfo.getPoolInTime() == null){
                       tmpMgrInfo.setPoolInTime(new Date());
                   }
                   tmpMgrInfo.setPoolScoreStatus(1);
               }
               else {
                   tmpMgrInfo.setPoolDeleteType(0);
                   tmpMgrInfo.setPoolIsBackbone(0);
                   tmpMgrInfo.setPoolTotalScore(totalScore);
                   tmpMgrInfo.setPoolUpdateTime(new Date());
                   if (poolMgrInfo.getPoolIsBackbone() == null || poolMgrInfo.getPoolIsBackbone() ==1 || poolMgrInfo.getPoolOutTime() == null){
                       tmpMgrInfo.setPoolOutTime(new Date());
                   }
                   tmpMgrInfo.setPoolScoreStatus(1);
               }
               modifiedInfos.add(tmpMgrInfo);
           }
            updatePlanRank(modifiedInfos);
        }
        catch (Exception e){
            log.error("统计骨干信息发生异常",e);
        }

        log.info("完成统计骨干信息");
    }
}
